package com.sitech.dao;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.SqlMapClientTemplate;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapException;
import com.ibatis.sqlmap.client.SqlMapExecutor;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
import com.sitech.component.Page;
import com.sitech.util.ibatis.CountStatementUtil;

/**
 * ClassName:BaseDAO Function: TODO ADD FUNCTION Reason: TODO ADD REASON
 * 
 * @author geutopia
 * @version
 * @since Ver 1.1
 * @Date Jun 25, 2010 2:03:45 PM
 * 
 * @see
 */
public class BaseDao
{
	private SqlMapClientTemplate sqlMapClientTemplate = new SqlMapClientTemplate();
	private static final Log logger = LogFactory.getLog(BaseDao.class);

	protected List query(String statementName)
	{
		return sqlMapClientTemplate.queryForList(statementName);
	}

	protected List query(String statementName, Object parameterObject)
	{
		return sqlMapClientTemplate.queryForList(statementName, parameterObject);
	}

	protected List query(String statementName, Object parameterObject, int start, int pageSize)
	{
		return sqlMapClientTemplate.queryForList(statementName, parameterObject, start, pageSize);
	}
	
	protected List query(String statementName, Object parameterObject, Page page)
	{
		if(page != null  && page.getPage() > 0  && page.getPageSize() > 0)
		{
			page.setRecords((int) queryTotalCount(statementName, parameterObject));
			return sqlMapClientTemplate.queryForList(statementName, parameterObject, (page.getPage()-1)*page.getPageSize(), page.getPage()*page.getPageSize());
		}
		else
		{
			return sqlMapClientTemplate.queryForList(statementName, parameterObject, (page.getPage()-1)*page.getPageSize(), page.getPage()*page.getPageSize());
		}
	}
	
	
	
	

	protected Object querySingle(String statementName)
	{
		return sqlMapClientTemplate.queryForObject(statementName);
	}

	protected Object querySingle(String statementName, Object parameterObject)
	{
		return sqlMapClientTemplate.queryForObject(statementName, parameterObject);
	}

	protected int update(String statementName)
	{
		return sqlMapClientTemplate.update(statementName);
	}

	protected int update(String statementName, Object parameterObject)
	{
		return sqlMapClientTemplate.update(statementName, parameterObject);
	}

	protected int delete(String statementName)
	{
		return sqlMapClientTemplate.delete(statementName);
	}

	protected int delete(String statementName, Object parameterObject)
	{
		return sqlMapClientTemplate.delete(statementName, parameterObject);
	}

	protected Object insert(String statementName)
	{
		return sqlMapClientTemplate.insert(statementName);
	}

	protected Object insert(String statementName, Object parameterObject)
	{
		return sqlMapClientTemplate.insert(statementName, parameterObject);
	}

	public List<Map> queryBySql(String sql)
	{
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("sql", sql);
		return (List<Map>) sqlMapClientTemplate.queryForList("selectBySql", paramMap);
	}

	public final void setSqlMapClient(SqlMapClient sqlMapClient)
	{
		this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
	}

	public void batchCreate(final String statementName, final List objectList)
	{

		SqlMapClientCallback callback = new SqlMapClientCallback()
		{

			public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException
			{

				executor.startBatch();

				for (Object object : objectList)
				{
					executor.insert(statementName, object);
				}

				executor.executeBatch();

				return null;

			}

		};
		this.sqlMapClientTemplate.execute(callback);
	}

	public void batchUpdate(final String statementName, final List objectList)
	{

		SqlMapClientCallback callback = new SqlMapClientCallback()
		{

			public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException
			{

				executor.startBatch();

				for (Object object : objectList)
				{
					executor.update(statementName, object);
				}

				executor.executeBatch();

				return null;

			}

		};
		this.sqlMapClientTemplate.execute(callback);
	}

	public void batchDelete(final String statementName, final List objectList)
	{

		SqlMapClientCallback callback = new SqlMapClientCallback()
		{

			public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException
			{

				executor.startBatch();

				for (Object object : objectList)
				{
					executor.delete(statementName, object);
				}
				executor.executeBatch();
				return null;
			}

		};
		this.sqlMapClientTemplate.execute(callback);
	}

	/**
	 * (non-Javadoc)
	 * @see com.sitech.dao.SerialNoDao#newSerialNo(java.lang.String)
	 */
	public String newSerialNo(String value)
	{

		return (String) querySingle("querySerialNoBySeq", value);
	}

	protected long queryTotalCount(String statementName, Object parameterObject)
	{
		prepareCountQuery(statementName);
		return (Long) sqlMapClientTemplate.queryForObject(CountStatementUtil.getCountStatementId(statementName), parameterObject);
	}

	protected long queryTotalCount(String statementName)
	{
		prepareCountQuery(statementName);
		return (Long) sqlMapClientTemplate.queryForObject(CountStatementUtil.getCountStatementId(statementName));
	}

	protected void prepareCountQuery(String statementName)
	{
		String countQuery = CountStatementUtil.getCountStatementId(statementName);
		if (logger.isDebugEnabled())
		{
			logger.debug("Convert " + statementName + " to " + countQuery);
		}
		SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();
		if (sqlMapClient instanceof ExtendedSqlMapClient)
		{
			SqlMapExecutorDelegate delegate = ((ExtendedSqlMapClient) sqlMapClient).getDelegate();
			try
			{
				delegate.getMappedStatement(countQuery);
			}
			catch (SqlMapException e)
			{
				delegate.addMappedStatement(CountStatementUtil.createCountStatement(delegate.getMappedStatement(statementName)));
			}
		}
	}

}
